home *** CD-ROM | disk | FTP | other *** search
/ Disc to the Future 2 / Disc to the Future Part II Programmer's Reference (Wayzata Technology)(6013)(1992).bin / MAC / THINKC / 4_0 / UUPC3 / (UUPC__) / DCPXFER.C < prev    next >
Text File  |  1992-02-10  |  17KB  |  655 lines

  1. /*            dcpxfer.c
  2.  
  3.             Revised edition of dcp
  4.  
  5.             Stuart Lynne May/87
  6.  
  7.             Copyright (c) Richard H. Lamb 1985, 1986, 1987
  8.             Changes Copyright (c) Stuart Lynne 1987
  9.             Portions Copyright ⌐ David Platt, 1992, 1991.  All Rights Reserved
  10.             Worldwide.
  11.  
  12. */
  13. /* "DCP" a uucp clone. Copyright Richard H. Lamb 1985,1986,1987 */
  14. /* file send routines */
  15. #include "dcp.h"
  16. #include <unix.h>
  17. #include <ctype.h>
  18.  
  19. static unsigned char    rpacket[MAXPACK+4];
  20. static unsigned char    spacket[MAXPACK+4];
  21. static long                xtime, tsize;
  22. static char                id[20];
  23. static struct tm        *now;
  24. static int                reportRfileError;
  25. /**/
  26. /***************SEND PROTOCOL***************************/
  27. /*
  28.  *  s d a t a
  29.  *
  30.  *  Send File Data
  31.  */
  32. sdata()
  33. {
  34.  
  35.     while( TRUE ) {
  36.  
  37.         if (( *sendpkt) ( spacket, size, 0 ))
  38.             return (0 );     /* send data */
  39.         if ((size=bufill((char *)spacket)) == 0)  /* Get data from file */
  40.             return( 'Z' );                         /* If EOF set state to that */
  41.         tsize += (long)size;
  42.     }
  43. }
  44.  
  45.  
  46. /*
  47.  *  b u f i l l
  48.  *
  49.  *  Get a bufferful of data from the file that's being sent.
  50.  *  Only control-quoting is done; 8-bit & repeat count prefixes are
  51.  *  not handled.
  52.  */
  53. bufill(buffer)
  54. char    *buffer;/* Buffer */
  55. {
  56.     return( read(fp, buffer, pktsize) );/* Handle partial buffer */
  57. }
  58.  
  59.  
  60. /*
  61.  *  s b r e a k
  62.  *
  63.  *  Send Break (EOT)
  64.  */
  65. sbreak()
  66. {
  67.     int    len, i;
  68.     sprintf((char *)spacket, "H");
  69.     if ((*sendmsg)(spacket, FALSE))
  70.         return(0);
  71.     if ((*getmsg)(spacket, &len))
  72.         return(0);
  73.     printmsg( 2, "Switch modes" );
  74.     if (spacket[1] == 'N')
  75.         return('G');
  76.     return('Y');
  77. }
  78.  
  79.  
  80. /**/
  81. /*
  82.  *  s e o f
  83.  *
  84.  *  Send End-Of-File.
  85.  */
  86. seof()
  87. {
  88.     int    len, i;
  89.     long int ticks, bytes;
  90. #ifdef    THINK_C
  91.     xtime = TickCount() - xtime;
  92. #endif
  93. /* send end-of-file indication, and perhaps receive a lower-layer ACK/NAK */
  94.     switch ((*eofpkt)()) {
  95.      case 'R':            /* retry */
  96.          printmsg(0, "Remote system asks that the file be resent");
  97.         lseek(fp, 0L, SEEK_SET);
  98.         size = bufill((char *)spacket);
  99.         tsize = (long)size;
  100.         (*filepkt)();                /* warmstart file-transfer protocol */
  101.          return 'D';                    /* stay in data phase */
  102.      case 'N':
  103.          return(0);                    /* cannot send file */
  104.      case 'Y':
  105.          break;                        /* sent, proceed */
  106.      case 'Q':
  107.          printmsg(0, "Remote gave up... try again later");
  108.         xfer_problems ++;
  109.          return 'A';
  110.     }
  111.     if((*getmsg)(rpacket, &len)) {
  112.         printmsg(0, "Never got yea/nay response at end-of-file");
  113.         xfer_problems ++;
  114.         return(0); /* didn't rec CY or CN packet */
  115.     }
  116.     if(strncmp((char *)rpacket, "CY", 2)) {
  117.         printmsg(0, "Remote had trouble with the file");
  118.         xfer_problems ++;
  119.         return(0); /* cant send file */
  120.     }
  121.     close(fp);
  122.     fp = (-1);
  123.      importpath( hostfile, fromfile );
  124.     UNLINK(hostfile);
  125.     printmsg( 1, "Transfer of %s (%s) completed.", fromfile, hostfile);
  126. #ifdef    THINK_C
  127.     ticks = xtime ? xtime : 1;
  128.     bytes = remote_stats.bsent - remote_stats.bstart;
  129.     printmsg( 0, "Copy succeeded, %ld chars/sec", (bytes * 60) / ticks);
  130.     time(&theTime);
  131.     now = localtime(&theTime);
  132.     fprintf( syslog, "%s!%s (%d/%d-%02d:%02d:%02d) -> %ld / %0.2f secs\n",
  133.                      nodename, id,
  134.                      now->tm_mday, (now->tm_mon+1),
  135.                      now->tm_hour, now->tm_min, now->tm_sec, tsize, xtime/60.0 );
  136. #else
  137.     printmsg( 0, "Copy succeeded");
  138. #endif
  139.     return('F');                    /* go get the next file to send */
  140. }
  141.  
  142.  
  143. /**/
  144. /*
  145.  *  s f i l e
  146.  *
  147.  *  Send File Header.
  148.  */
  149. sfile()
  150. {
  151.     int    i, len, resp;
  152.     char * cp;
  153.     char tmp[50];
  154.     if (fp == -1) {/* If not already open, */
  155.         printmsg( 3, "looking for next file..." );
  156.         if (getfile()) { /* get next file from current work*/
  157.             if (fw != (FILE *)NULL) {
  158.                 fclose(fw);
  159.                 fw = (FILE *)NULL;
  160.             }
  161.             UNLINK( cfile );/* close and delete completed workfile */
  162.             if (Main_State == Cancel_Call) {
  163.                 return ('H'); /* semi-polite disconnect */
  164.             }
  165.             return('B'); /* end sending session */
  166.         }
  167.  
  168.          importpath( hostfile, fromfile );
  169.  
  170.       if (*tofile == 'S')  {
  171.          printmsg(3, "Opening %s (%s) for sending.", fromfile, hostfile);
  172.         fp = OPEN (hostfile, 0);/* open the file to be sent */
  173.          if (fp == -1)
  174.          {
  175.              if (errno == ENOENT) {
  176.                  printmsg(0, "sfile: File %s (%s) does not exist, skipped", fromfile, hostfile);
  177.                  return 'F';
  178.              } else {
  179.                    printmsg(0, "sfile: Cannot open file %s (%s), error %d", fromfile, hostfile, errno);
  180.                 xfer_problems ++;
  181.                 return 'A';
  182.             }
  183.          } /* if */
  184.       } /* if */
  185. /*--------------------------------------------------------------------*/
  186. /*    If the target is a directory, automatically put a file into     */
  187. /*    it rather than on it!                                           */
  188. /*--------------------------------------------------------------------*/
  189.       else {
  190. #ifdef STAT
  191.          struct  stat    statbuf;
  192.  
  193.          if ((hostfile[strlen(hostfile) - 1] == '/') ||
  194.              ((stat(hostfile , &statbuf) == 0) &&
  195.               (statbuf.st_mode & S_IFDIR)))
  196.          {
  197.             char *slash = strrchr( rmtfname, '/');
  198.             if ( slash == NULL )
  199.                slash = rmtfname;
  200.             else
  201.                slash ++ ;
  202.             printmsg(3,"sfile: Destination \"%s\" is directory, appending filename \"%s\"", hostfile, slash);
  203.             if (hostfile[strlen(hostfile) - 1] != '/')
  204.                strcat(hostfile, "/");
  205.             strcat( hostfile, slash );
  206.          } /* if */
  207. #endif
  208.       } /* else */
  209.    } /* if */
  210.    else
  211.       return 'A'; /* Something's already open.  We're in trouble! */
  212.  
  213.     sscanf(tofile, "%s %s %s %s", &tmp, &tmp, &tmp, &id);
  214.     if (*tofile == 'S') {
  215.         printmsg( 1, "Sending %s (%s) as %s", fromfile, hostfile, tmp);
  216.         printmsg( 0, "Send %s -> %s", fromfile, tmp);
  217.     } else {
  218.         printmsg( 1, "Sending %s (%s) as %s", fromfile, hostfile, tmp);
  219.         printmsg( 0, "Recv %s <- %s", fromfile, tmp);
  220.     }
  221.     xtime = TickCount();
  222.     remote_stats.bstart = remote_stats.bsent;
  223.    if ((*sendmsg)((char *) tofile, FALSE))
  224.            return 0;      /* send 'S fromfile tofile user - tofile 0666' */
  225.  
  226.    if ((*getmsg)((char *) spacket, &len))
  227.       return 0;
  228.  
  229.    if (spacket[1] != 'Y') {
  230.            if (spacket[0] == 'R') {
  231.                    printmsg(0, "Cannot fetch file from remote");
  232.            } else {
  233.             xfer_problems ++;
  234.                switch (spacket[2]) {
  235.                    case '2':
  236.                        printmsg(0, "Cannot send; remote reports trouble with work files");
  237.                        break;
  238.                    case '4':
  239.                        printmsg(0, "Cannot send; remote has denied permission");
  240.                        break;
  241.                    default:
  242.                        printmsg(0, "Cannot send; remote didn't say why");
  243.                        break;
  244.                }
  245.            }
  246.       return 'A';    /* If other side says no, then quit */
  247.    }
  248.  
  249.    if (*tofile == 'S') {
  250.         size = bufill((char *)spacket);
  251.         tsize = (long)size;
  252.     }
  253.    else  {
  254.         if ((fp = CREAT( tofile, 0775, 'b' )) == -1) { 
  255.             /* Try to open a new file */
  256.             printmsg( 0, "cannot create %s", tofile ); /* Give up if can't */
  257.             return('A');
  258.         }
  259.    }
  260.  
  261.     (*filepkt)(); /* warmstart file-transfer protocol */
  262.     return(char)(*tofile == 'S' ? 'D' : 'R');
  263.                               /* Is this how to do it ? */
  264.  
  265. }
  266.  
  267.  
  268. /**/
  269. /*
  270.  *  s i n i t
  271.  *
  272.  *  Send Initiate: send this host's parameters and get other side's back.
  273.  */
  274. sinit()
  275. {
  276.     if ((*openpk)())
  277.         return('X');
  278.     return('B');
  279. }
  280.  
  281. /*
  282.    g e t f i l e
  283.  
  284.    Reads the next line from the presently open call file
  285.    (*workfile) and determines from this the next file to be sent
  286.    (*fromfile).  If there are no more, TRUE is returned.
  287. */
  288. static int getfile()
  289. {
  290.    char line[BUFSIZ];
  291.    char fname[FILENAME_MAX], tname[FILENAME_MAX], dname[FILENAME_MAX];
  292.    char type[5], who[20], flgs[16];
  293.    int i;
  294.  
  295.    if (fgets(line, BUFSIZ, fw) == (char *)NULL)
  296.       return TRUE;
  297.  
  298.    i = strlen(line) - 1;
  299.    if (line[i] == '\n')            /* remove new_line from card */
  300.       line[i] = '\0';
  301.  
  302.    sscanf(line, "%s %s %s %s %s %s", type, fname, tname, who, flgs, dname);
  303.  
  304.    strcpy(tofile, line);
  305.    if (*type == 'R')  {
  306.       del_file_flag = FALSE;        /* we aren't about to delete anything! */
  307.       strcpy(fromfile, tname);      /* NOTE - strange use of the name 'fromfile' */
  308.       strcpy( rmtfname, fname );    /* Save for sfile() magic  */
  309.    }
  310.    else if (strcmp(dname, "D.0") == 0)  {
  311.            del_file_flag = FALSE;
  312.            strcpy(fromfile, fname);
  313.    }
  314.    else  {
  315.            del_file_flag = TRUE;
  316.            strcpy(fromfile, dname); /* correct name according to Nutshell */
  317.    }
  318.  
  319.    printmsg(3, "getfile: fromfile=%s, tofile=%s.", fromfile, tofile);
  320.  
  321.    return FALSE;
  322.  
  323. } /*getfile*/
  324.  
  325.  
  326. /**/
  327. /*********************** MISC SUB SUB PROTOCOL *************************/
  328. /*
  329. **
  330. **schkdir
  331. ** scan the dir
  332. */
  333. schkdir()
  334. {
  335.     char    c;
  336.     c = scandir();
  337.     if (c == 'Q') {
  338.         return('Y');
  339.     }
  340.     if (c == 'S') {
  341.         sprintf((char *)rpacket, "HN");
  342.         if ((*sendmsg)(rpacket, FALSE))
  343.             return(0);
  344.     }
  345.     return('B');
  346. }
  347.  
  348.  
  349. /**/
  350. /*
  351.  *
  352.  *      endp() end protocol
  353.  *
  354. */
  355. endp(polite)
  356. int polite;
  357. {
  358.     if (polite) {
  359.         sprintf((char *)rpacket, "HY");
  360.         (*sendmsg)(rpacket, TRUE); /* dont wait for ACK */
  361.         zzz(2);            /* allow peer a moment to hear msg before hangup occurs */
  362.     } else {
  363.         printmsg(0, "Closing connection (cancelled by user)");
  364.     }
  365.     (*closepk)();
  366.     printmsg( 0, "Conversation complete");
  367.     return('P');
  368. }
  369.  
  370.  
  371. /**/
  372. /***********************RECIEVE PROTOCOL**********************/
  373. /*
  374.  *  r d a t a
  375.  *
  376.  *  Receive Data
  377.  */
  378. rdata()
  379. {
  380.     int    len, wrote;
  381.     long int ticks, bytes;
  382.     int resp;
  383.     resp = (*getpkt)(rpacket, &len);
  384.     if (resp == 'R') { /* Retransmission required */
  385.         return resp;
  386.     }
  387.     if (resp != 0)
  388.         return(0);
  389.     if (len > 0) {
  390.         wrote = write(fp, (char *)rpacket, len);/* Write the data to the file */
  391.         tsize += (long)len;
  392.         if (len != wrote && !reportRfileError) {
  393.             printmsg( 0, "Write error, tried %d, wrote %d", len, wrote);
  394.             reportRfileError = 1;
  395.         }
  396.         return('D');/* Remain in data state */
  397.     }
  398.     if (len < 0) {
  399.         wrote = write(fp, (char *)rpacket, -len);/* Write the final data to the file */
  400.         tsize -= (long)len;
  401.         if (-len != wrote && !reportRfileError) {
  402.             printmsg( 0, "Write error, tried %d, wrote %d", -len, wrote);
  403.             reportRfileError = 1;
  404.         }
  405.     }
  406. #ifdef    THINK_C
  407.     xtime = TickCount() - xtime;
  408. #endif
  409.     close(fp);
  410.     fp = -1;
  411.     if ((*sendresp)(OK)) {
  412.         return (0);
  413.     }
  414.     if (reportRfileError) {
  415.         strcpy((char *)spacket, "CN5");
  416.     } else {
  417.         strcpy((char *)spacket, "CY");
  418.     }
  419.     if ((*sendmsg)(spacket, FALSE)) {
  420.         return (0);
  421.     }
  422.     ticks = xtime ? xtime : 1;
  423.     bytes = remote_stats.breceived - remote_stats.bstart;
  424.     if (reportRfileError) {
  425.         printmsg( 0, "Copy failed");
  426.         xfer_problems ++;
  427.     } else {
  428.         printmsg( 0, "Copy succeeded, %ld chars/sec", (bytes * 60) / ticks);
  429.     }
  430.     time(&theTime);
  431.     now = localtime(&theTime);
  432.     fprintf( syslog, "%s!%s (%d/%d-%02d:%02d:%02d) <- %ld / %0.2f secs\n",
  433.                      rmtname, id,
  434.                      now->tm_mday, (now->tm_mon+1),
  435.                      now->tm_hour, now->tm_min, now->tm_sec, tsize, xtime/60.0 );
  436.     return('F');
  437. }
  438.  
  439.  
  440. /*
  441.    r f i l e
  442.  
  443.    Receive File Header
  444. */
  445.  
  446. int rfile()
  447. {
  448.    char tmpfilename[FILENAME_MAX];
  449.    char buf[BUFSIZ];
  450.    char *flds[10], *cp;
  451.    int rx;                /* TRUE = Receive of file in progress  */
  452.    int nondefault;        /* TRUE = non default directory target */
  453.    int public;              /* TRUE = destined for public folder   */
  454.    int numflds;
  455.  
  456.    FILE *stream;
  457.  
  458.    printmsg(3, "rfile: entered");
  459.  
  460.    if (Main_State == Cancel_Call) {
  461.       return ('H');
  462.    }
  463.    
  464.    reportRfileError = 0;
  465.  
  466.    for (cp = buf; ; ) {
  467.       int len;
  468.       if ((*getmsg)((char *) rpacket, &len))
  469.          return 0;
  470.       memcpy(cp, (char *) rpacket, len);
  471.       cp += len;
  472.       if (cp[-1] == '\0')
  473.          break;
  474.    }
  475.  
  476. /*--------------------------------------------------------------------*/
  477. /*        Return if the remote system has no more data for us         */
  478. /*--------------------------------------------------------------------*/
  479.  
  480.    if ((buf[0] & 0x7f) == 'H')
  481.       return 'C';    /* the other side (master) is done */
  482.  
  483. /*--------------------------------------------------------------------*/
  484. /*                  Begin transforming the file name                  */
  485. /*--------------------------------------------------------------------*/
  486.  
  487.    printmsg(3, "rfile: command \"%s\"", buf);
  488.  
  489.    numflds = getargs( buf, flds );
  490.  
  491.    rx = (*flds[0] == 'S');         /* flag we are receiving a file */
  492.  
  493.    if (rx)
  494.       cp = flds[2];
  495.    else
  496.       cp = flds[1];
  497.  
  498.    nondefault = (strchr(cp , '/') != NULL) || (strchr(cp , '\\') != NULL);
  499.    strcpy(tmpfilename,cp);
  500.  
  501.     if ( strncmp( cp, "~/", 2 ) == SAME ) {
  502.         sprintf( tmpfilename, "%s%s", pubdir, cp+1);
  503.         public = 1;
  504.     } else {
  505.         strcpy( tmpfilename, cp );
  506.         public = 0;
  507.     }
  508.    printmsg(3, "rfile: destination \"%s\"", cp);
  509.  
  510. /*--------------------------------------------------------------------*/
  511. /* If the name has a path and we don't allow it, reject the transfer  */
  512. /*--------------------------------------------------------------------*/
  513.  
  514.    if (nondefault && ! public) 
  515.    {
  516.         if (rx) {
  517.             printmsg(0,"File %s not destined for spool directory, rejected.", cp);
  518.             sprintf((char *)rpacket, "SN2");
  519.         } else {
  520.             printmsg(0,"File %s not in spool directory, will not be sent", cp);
  521.             sprintf((char *)rpacket, "RN2");
  522.         }
  523.         if ((*sendmsg)(rpacket, FALSE))
  524.             return(0);
  525.         return 'F'; /* Reject this one but keep going */
  526.    }
  527.  
  528. #ifdef STAT
  529. /*--------------------------------------------------------------------*/
  530. /*       Check if the name is a directory name (end with a '/')       */
  531. /*--------------------------------------------------------------------*/
  532.  
  533.    if (rx && ((cp[strlen(cp) - 1] == '/') ||
  534.               ((stat(fromfile , &statbuf) == 0) &&
  535.                (statbuf.st_mode & S_IFDIR))))
  536.    {
  537.       printmsg(3, "rfile: destination is directory \"%s\"", flds[1]);
  538.       if ((cp = strrchr(flds[1], '/')) == nil(char))
  539.          cp = flds[1];
  540.       else
  541.          cp++;
  542.       printmsg(3, "rfile: directory only, adding \"%s\"", cp);
  543.  
  544.       if ( tmpfilename[ strlen( tmpfilename ) - 1 ] != '/')
  545.          strcat(tmpfilename, "/");
  546.       strcat(tmpfilename, cp);
  547.    } /* if */
  548. #endif
  549.  
  550.    if (rx)
  551.       printmsg(3, "rfile: receive file \"%s\"", tmpfilename);
  552.  
  553. /*--------------------------------------------------------------------*/
  554. /*          Let host munge filename as appropriate                    */
  555. /*--------------------------------------------------------------------*/
  556.  
  557. #ifdef IMPORTREMOTE
  558.    importpath(tofile, tmpfilename, rmtname);
  559. #else
  560.    importpath(tofile, tmpfilename);
  561. #endif
  562.  
  563.    printmsg(3, "rfile: host file \"%s\"", tofile);
  564.  
  565. /*--------------------------------------------------------------------*/
  566. /*       Don't allow files to be overlaid                             */
  567. /*--------------------------------------------------------------------*/
  568.  
  569.    if (rx && nondefault)
  570.    {
  571.       stream = fopen(tofile, "r");  /* Determine if the file exists
  572.                                        by opening it for input       */
  573.       if ( stream != NULL )         /* Does it exist?                */
  574.       {
  575.         fclose(stream);
  576.         printmsg(0, "rfile: Cannot receive \"%s\", \"%s\" exists",
  577.                      flds[1], tofile);
  578.         sprintf((char *)rpacket, "SN4");
  579.         if ((*sendmsg)(rpacket, FALSE))
  580.             return(0);
  581.         return 'F'; /* Reject this one but keep going */
  582.       }
  583.    } /* if rx */
  584.  
  585. /*--------------------------------------------------------------------*/
  586. /*            The filename is transformed, try to open it             */
  587. /*--------------------------------------------------------------------*/
  588.  
  589.    if (rx)
  590.    {
  591.         fp = CREAT( tofile, 0775, 'b' );
  592.  
  593.         if (fp == -1){
  594.             printmsg(0, "rfile: cannot open file %s (%s).",
  595.                         tmpfilename, tofile);
  596.             sprintf((char *)rpacket, "SN2");
  597.             if ((*sendmsg)(rpacket, FALSE))
  598.                 return(0);
  599.             return 'F'; /* Reject this one but keep going */
  600.         } /* if */
  601.  
  602.         printmsg( 0, "Rcve %s <- %s", tofile, flds[1] );
  603.         remote_stats.bstart = remote_stats.breceived;
  604.         sprintf((char *)rpacket, "SY");
  605.         xtime = TickCount();
  606.         tsize = 0L;
  607.         strcpy(id, flds[3]);
  608.         if ((*sendmsg)(rpacket, FALSE))
  609.             return(0);
  610.         (*filepkt)(); /* init for file transfer */
  611.         return('D'); /* Switch to data state */
  612.    } /* if rx */
  613.    else
  614.    {
  615.       printmsg(3, "Opening %s (%s) for sending.", flds[1], tofile);
  616.         fp = OPEN(tofile, 0);/* open the file to be sent */
  617.         if (fp == -1) {/* If bad file pointer, give up */
  618.          printmsg(0, "rfile: Cannot open file %s (%s).", flds[1], tofile);
  619.         sprintf((char *)rpacket, "RN2");
  620.         if ((*sendmsg)(rpacket, FALSE))
  621.             return(0);
  622.         return 'F'; /* Reject this one but keep going */
  623.       } /* if */
  624.  
  625.       strcpy( (char *) rpacket, "RY");
  626.       if ((*sendmsg)((char *) rpacket, FALSE))
  627.          return 0;
  628.       printmsg( 1, "Sending %s (%s) as %s", flds[1], hostfile, tofile);
  629.       printmsg( 0, "Send %s -> %s", flds[1], tofile);
  630.       size = bufill((char *)spacket);
  631.       tsize = (long)size;
  632.       (*filepkt)(); /* init for file transfer */
  633.       return 'S';     /* Switch to send data state */
  634.    } /* else */
  635.  
  636. } /*rfile*/
  637.  
  638.  
  639. /**/
  640. /*
  641.  *  r i n i t
  642.  *
  643.  *  Receive Initialization
  644.  */
  645. rinit()
  646. {
  647.     if ((*openpk)())
  648.         return(0);
  649.     return('F');
  650. }
  651.  
  652.  
  653.  
  654.  
  655.